﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Messaging;

namespace MQMove
{
    class Program
    {
        static void Main(string[] args)
        {
            if (args.Length == 3)
            {
                MoveMessage(Int32.Parse(args[0]), args[1], args[2]);
            }
            else
            {
                DisplayUsage();
            }
        }

        private static void MoveMessage(int numMessagesToProcess, string srcQueueName, string dstQueueName)
        {
            int messagesProcessed = 0;

            MessageQueueTransaction trans = new MessageQueueTransaction();
            
            MessageQueue srcQueue = new MessageQueue(srcQueueName);
            MessageQueue dstQueue = new MessageQueue(dstQueueName);

            // Specify message properties to retrieve from messages
            //srcQueue.MessageReadPropertyFilter.UseEncryption = true;


            // If you move messages to remote private queues then it's not possible to check if the destination queue is transactional
            // Moving a message from a queue with different transactional setting than the receiving queue will cause the message to be lost
            // Checking for transactional queue support is currently not supported for remote queues

            //if (!srcQueue.Transactional)
            //{
            //    ExitWithError(1, "Source queue is not transactional.");
            //}

            //if (!dstQueue.Transactional)
            //{
            //    ExitWithError(1, "Destination queue is not transactional.");
            //}



            trans.Begin();

            try
            {
                Message msg = srcQueue.Receive(new TimeSpan(0, 0, 2), trans);
                while (msg != null)
                {
                    dstQueue.Send(msg, trans);
                    messagesProcessed++;

                    if (numMessagesToProcess > 0 && messagesProcessed >= numMessagesToProcess)
                        break;

                    msg = srcQueue.Receive(new TimeSpan(0, 0, 2), trans);
                }
                trans.Commit();
            }
            catch (MessageQueueException ex)
            {
                if (ex.MessageQueueErrorCode != MessageQueueErrorCode.IOTimeout)
                {
                    trans.Abort();
                    ExitWithError(1, ex.Message);
                }
                else
                {
                    Console.WriteLine("No more messages on queue.");
                    trans.Commit();
                }
            }
            catch (Exception ex)
            {
                trans.Abort();
                ExitWithError(1, ex.Message);
            }
            finally
            {
                srcQueue.Close();
                dstQueue.Close();
            }

            Environment.Exit(0);
        }



        private static void ExitWithError(int p, string p_2)
        {
            if (!String.IsNullOrEmpty(p_2))
                Console.WriteLine("An error occured. " + p_2);

            Environment.Exit(p);
        }


        private static void DisplayUsage()
        {

            Console.WriteLine("MQMove by Alexander Winkler, www.alexanderwinkler.se");
            Console.WriteLine("Moves messages to another queue.");
            Console.WriteLine("Usage: MQMove <NumOfMessagesToProcess> <SourceQueuePath> <DestinationQueuePath>");
            Console.WriteLine("If NumOfMessagesToProcess is 0 then all messages available");
            Console.WriteLine("on the queue will be processed.");
            Console.WriteLine("Example: MQMove 1 .\\private$\\test1 .\\private$\\test2");
            
        }
    }
}
